#include <memory>

#include <boost/test/unit_test.hpp>
//#include <boost/test/included/unit_test_framework.hpp>

#include<boost/bind.hpp>

#include "boosttestsupport.h"

#include "graphsupporttest/TestBaseGraph.h"
#include "graphsupporttest/TestGraphGenerate.h"
#include "cppfeaturestests/TestCppFeatures.h"
#include "graphsupporttest/TestFacilityLocationSolver.h"
#include "graphsupporttest/TestPrimalDualFactor3Solver.h"

class TestSuite : public boost::unit_test::test_suite
{
public:
	TestSuite( const char * name )
		: boost::unit_test::test_suite( name )
	{
	}
};

void cppFeaturesTestSuite( boost::unit_test::test_suite * suite )
{
	std::auto_ptr< TestSuite > cppFeaturesTestSuite( new TestSuite( "C++ features tests" ) );

	cppFeaturesTestSuite->add( BOOST_TEST_CASE( & TestTrivialAccumulate ) );
	cppFeaturesTestSuite->add( BOOST_TEST_CASE( & TestIfThnEls ) );
	cppFeaturesTestSuite->add( BOOST_TEST_CASE( & TestVecToString ) );
	cppFeaturesTestSuite->add( BOOST_TEST_CASE( & TestRTTI ) );

	suite->add( cppFeaturesTestSuite.release() );
}

void graphTestSuite( boost::unit_test::test_suite * suite )
{
	std::auto_ptr< TestSuite > graphTestSuite( new TestSuite( "Base graph tests" ) );

	graphTestSuite->add( BOOST_TEST_CASE( & TestCycleGraphCreate ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestGraphCopy ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestFacilitiesGraph ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestGraphOperation ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestGenNearNeighborDiffer ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestBipartite ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestCompoundOperation ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestMakeSymmOperation ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestAddChpExpWeightsOperation ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestAddChpExpErases_2ndBP_to_1stBP_edges ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestDefaultGenerator ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestRandomSetupInGeneration ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestTriangleInequalityCloseOperation ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestGenerateFacilityPrices ) );
	graphTestSuite->add( BOOST_TEST_CASE( & TestCompoundGraphOperation ) );

	suite->add( graphTestSuite.release() );
}

void facilsolveTestSuite( boost::unit_test::test_suite * suite )
{
	std::auto_ptr< TestSuite > facilsolveTestSuite( new TestSuite( "Facility Location problem solver test suit" ) );

	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestFacilityLocationSolver ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestSolutionDoesnotExist ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestBinRunFoundAtLeastPredefined ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestCompoundSolver ) );

	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestPrimDualSolvContext ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestFindWitnessForVertex ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & Test_FindAllWitnesses_RandomCases ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestComputeSpecialEdgesSquareSubgraph ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestComputeMaximalIndependentSet ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestComputeMaximalIndependentSet_RandomCases ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestFacilityAssociation ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestFacilityAssociation_Random ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestSolvContext__initFromGraph ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestFactor3solver ) );
	facilsolveTestSuite->add( BOOST_TEST_CASE( & TestFactor3solver_Random ) );

	suite->add( facilsolveTestSuite.release() );
}

boost::unit_test::test_suite * init_unit_test_suite(int argc, char * * argv)
{
	boost::unit_test::test_suite * suite( BOOST_TEST_SUITE( "Master Suite" ) );

	graphTestSuite( suite );
	cppFeaturesTestSuite( suite );
	facilsolveTestSuite( suite );

	return suite;
}
